package com.shwread.android.qysw.step;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.util.Log;

import com.shwread.android.qysw.activity.MainActivity;
import com.shwread.android.qysw.step.model.UserHealthyDataModel;
import com.shwread.android.qysw10000136.R;


/**
 * Created by fantasy on 16/1/22.
 */
public class StepService extends Service {
    private static final String TAG = "fitgroup.StepService";
    private SharedPreferences mSettings;
    private PedometerSettings mPedometerSettings;
    private SharedPreferences mState;
    private SharedPreferences.Editor mStateEditor;
    private Utils mUtils;
    private SensorManager mSensorManager;
    private Sensor mSensor;
    private StepDetector mStepDetector;
    // private StepBuzzer mStepBuzzer; // used for debugging
    private static StepDisplayer mStepDisplayer;
    //    private PaceNotifier mPaceNotifier;
    private DistanceNotifier mDistanceNotifier;
    private CaloriesNotifier mCaloriesNotifier;
    private PowerManager.WakeLock wakeLock;
    private NotificationManager mNM;

    private int mSteps;
    private int mPace;
    private double mDistance;
    private float mSpeed;
    private double mCalories;
    private Notification notification;
    private PendingIntent contentIntent;

    private long currentTime;

    /**
     * Class for clients to access.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with
     * IPC.
     */
    public class StepBinder extends Binder {
        public StepService getService() {
            return StepService.this;
        }
    }

    @Override
    public void onCreate() {
        Log.i("darren-------", "[SERVICE] OnCreate");
        super.onCreate();

        mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//        showNotification(mSteps);
        currentTime = System.currentTimeMillis();

        // Load settings
        mSettings = PreferenceManager.getDefaultSharedPreferences(this);
        mPedometerSettings = new PedometerSettings(mSettings);
        mState = getSharedPreferences("state", 0);

        mUtils = Utils.getInstance();
        mUtils.setService(this);
//        mUtils.initTTS();

        acquireWakeLock();

        // Start detecting
        mStepDetector = new StepDetector();
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        registerDetector();

        // Register our receiver for the ACTION_SCREEN_OFF action. This will make our receiver
        // code be called whenever the phone enters standby mode.
        //注册屏幕熄灭事件的广播监听
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        registerReceiver(mReceiver, filter);

        mStepDisplayer = new StepDisplayer(mPedometerSettings, mUtils);
        // mStepDisplayer.setSteps(mSteps = mState.getInt("steps", 0));
        mStepDisplayer.setSteps(mSteps = UserStepModel.getInstance().getUserTodayStep());
        mStepDisplayer.addListener(mStepListener);
        mStepDetector.addStepListener(mStepDisplayer);

//        mPaceNotifier = new PaceNotifier(mPedometerSettings, mUtils);
//        mPaceNotifier.setPace(mPace = mState.getInt("pace", 0));

//        mPaceNotifier.addListener(mPaceListener);
//        mStepDetector.addStepListener(mPaceNotifier);
//
        mDistanceNotifier = new DistanceNotifier(mDistanceListener, mPedometerSettings, mUtils);
        mDistanceNotifier.setDistance(mDistance = UserStepModel.getInstance().getUserTodayDistance());
//
        mStepDetector.addStepListener(mDistanceNotifier);

//        mSpeedNotifier = new SpeedNotifier(mSpeedListener, mPedometerSettings, mUtils);
//        mSpeedNotifier.setSpeed(mSpeed = mState.getFloat("speed", 0));
//
//        mPaceNotifier.addListener(mSpeedNotifier);

        mCaloriesNotifier = new CaloriesNotifier(mCaloriesListener, mPedometerSettings, mUtils);
        mCaloriesNotifier.setCalories(mCalories = UserStepModel.getInstance().getUserTodayCalories());

        mStepDetector.addStepListener(mCaloriesNotifier);

        // Used when debugging:
        // mStepBuzzer = new StepBuzzer(this);
        // mStepDetector.addStepListener(mStepBuzzer);

        reloadSettings();

        // Tell the user we started.
        // Toast.makeText(this, getText(R.string.started), Toast.LENGTH_SHORT).show();
    }

    public static void setStep(int steps) {
        mStepDisplayer.setSteps(steps);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("logger-------", "[SERVICE] onStartCommand");
        if (null == intent) {
            Log.i("logger-------", "[SERVICE] onStartCommand------null--intent");
//            mNM.cancel(R.string.app_name);
//            stopForeground(true);
        }
        return START_STICKY;
        // return Service.START_REDELIVER_INTENT;
        //   return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i("logger-------", "[SERVICE] onDestroy");
        unregisterReceiver(mReceiver);
        unregisterDetector();
        mStateEditor = mState.edit();
        stopForeground(true);

        wakeLock.release();

        super.onDestroy();

        mSensorManager.unregisterListener(mStepDetector);

    }

    /**
     * 将Sensor和自定的监听事件绑定起来
     */
    private void registerDetector() {
        mSensor = mSensorManager.getDefaultSensor(
                Sensor.TYPE_ACCELEROMETER /*|
            Sensor.TYPE_MAGNETIC_FIELD |
            Sensor.TYPE_ORIENTATION*/);
        mSensorManager.registerListener(mStepDetector,
                mSensor,
                SensorManager.SENSOR_DELAY_FASTEST);
    }

    private void unregisterDetector() {
        mSensorManager.unregisterListener(mStepDetector);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("logger-------", "[SERVICE] onBind");
        // Log.i(TAG, "[SERVICE] onBind");
        return mBinder;
    }

    @Override
    public void onRebind(Intent intent) {
        Log.i("logger-------", "[SERVICE] onRebind");
        super.onRebind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("logger-------", "[SERVICE] onUnbind");
        return super.onUnbind(intent);
    }

    /**
     * Receives messages from activity.
     */
    private final IBinder mBinder = new StepBinder();

    public interface ICallback {
        public void stepsChanged(int value);

        public void paceChanged(int value);

        public void distanceChanged(double value);

        public void speedChanged(float value);

        public void caloriesChanged(double value);
    }

    private ICallback mCallback;

    public void registerCallback(ICallback cb) {
        Log.i("darren", "registerCallback");
        mCallback = cb;
        //mStepDisplayer.passValue();
        //mPaceListener.passValue();
    }

    private int mDesiredPace;
    private float mDesiredSpeed;

    /**
     * Called by activity to pass the desired pace value,
     * whenever it is modified by the user.
     *
     * @param desiredPace
     */
//    public void setDesiredPace(int desiredPace) {
//        mDesiredPace = desiredPace;
//        if (mPaceNotifier != null) {
//            mPaceNotifier.setDesiredPace(mDesiredPace);
//        }
//    }

    /**
     * Called by activity to pass the desired speed value,
     * whenever it is modified by the user.
     *
     * @param desiredSpeed
     */
    public void setDesiredSpeed(float desiredSpeed) {
        mDesiredSpeed = desiredSpeed;
//        if (mSpeedNotifier != null) {
//            mSpeedNotifier.setDesiredSpeed(mDesiredSpeed);
//        }
    }

    public void reloadSettings() {
        mSettings = PreferenceManager.getDefaultSharedPreferences(this);

        if (mStepDetector != null) {
            mStepDetector.setSensitivity(
                    Float.valueOf(mSettings.getString("sensitivity", "21.75"))//设置灵敏度
            );
        }
        if (mStepDisplayer != null) mStepDisplayer.reloadSettings();
//        if (mPaceNotifier != null) mPaceNotifier.reloadSettings();
//        if (mDistanceNotifier != null) mDistanceNotifier.reloadSettings();
//        if (mSpeedNotifier != null) mSpeedNotifier.reloadSettings();
//        if (mCaloriesNotifier != null) mCaloriesNotifier.reloadSettings();

    }

    public void resetValues() {
        mStepDisplayer.setSteps(0);
//        mPaceNotifier.setPace(0);
//        mDistanceNotifier.setDistance(0);
//        mSpeedNotifier.setSpeed(0);
//        mCaloriesNotifier.setCalories(0);
    }

    /**
     * Forwards pace values from PaceNotifier to the activity.
     */
    private StepDisplayer.Listener mStepListener = new StepDisplayer.Listener() {
        public void stepsChanged(int value) {
            boolean isWrite = (System.currentTimeMillis() - currentTime) / 1000 > 10;
            if (isWrite) {
                currentTime = System.currentTimeMillis();
                mStateEditor = mState.edit();
                // mStateEditor.putInt("steps", mSteps);
                Log.i("darren", "ServiceupdateStep" + mSteps);
                UserStepModel.getInstance().updateTodayHealthyData(mSteps, mCalories, mDistance);
                UserHealthyDataModel.getInstance().submitTodayStep(mSteps);
//                UserStepModel.getInstance().updateTodayStep(mSteps);
//                UserStepModel.getInstance().updateTodayCalories(mCalories);
//                UserStepModel.getInstance().updateTodayDistance(mDistance);
//                mStateEditor.putInt("pace", mPace);
//                mStateEditor.putFloat("distance", mDistance);
//                mStateEditor.putFloat("speed", mSpeed);
//                mStateEditor.putFloat("calories", mCalories);
//                mStateEditor.commit();
                showNotification(mSteps);
            }
            mSteps = value;
            passValue();
        }

        public void passValue() {
            /**
             * 当数据发生更改时，回调此方法，activity界面会进行UI的更改
             */
            if (mCallback != null) {
                mCallback.stepsChanged(mSteps);
            }
        }
    };

    /**
     * Forwards distance values from DistanceNotifier to the activity.
     */
    private DistanceNotifier.Listener mDistanceListener = new DistanceNotifier.Listener() {
        public void valueChanged(double value) {
            mDistance = value;
            passValue();
        }

        public void passValue() {
            if (mCallback != null) {
                mCallback.distanceChanged(mDistance);
            }
        }
    };

    /**
     * Forwards calories values from CaloriesNotifier to the activity.
     */
    private CaloriesNotifier.Listener mCaloriesListener = new CaloriesNotifier.Listener() {
        public void valueChanged(double value) {
            mCalories = value;
            passValue();
        }

        public void passValue() {
            if (mCallback != null) {
                mCallback.caloriesChanged(mCalories);
            }
        }
    };

    /**
     * Show a notification while this service is running.
     */
    private void showNotification(int steps) {
        initNotification();
        notification.setLatestEventInfo(this, getText(R.string.app_name),
                "今日步数：" + steps, contentIntent);

        startForeground(1, notification);
    }

    private void initNotification() {
        notification = new Notification(R.drawable.ic_launcher, null,
                System.currentTimeMillis());
        notification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
        Intent pedometerIntent = new Intent();
        pedometerIntent.setComponent(new ComponentName(this, MainActivity.class));
        pedometerIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        contentIntent = PendingIntent.getActivity(this, 0,
                pedometerIntent, 0);
    }


    // BroadcastReceiver for handling ACTION_SCREEN_OFF.
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Check action just to be on the safe side.
            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                Log.i("logger------", "--------broadcastReceiver:--" + intent.getAction());
                // Unregisters the listener and registers it again.
                StepService.this.unregisterDetector();
                StepService.this.registerDetector();
                if (mPedometerSettings.wakeAggressively()) {
                    wakeLock.release();
                    acquireWakeLock();
                }
            }
        }
    };

    private void acquireWakeLock() {
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        int wakeFlags;
        if (mPedometerSettings.wakeAggressively()) {
            wakeFlags = PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
        } else if (mPedometerSettings.keepScreenOn()) {
            wakeFlags = PowerManager.SCREEN_DIM_WAKE_LOCK;
        } else {
            wakeFlags = PowerManager.PARTIAL_WAKE_LOCK;
        }
        wakeLock = pm.newWakeLock(wakeFlags, TAG);
        wakeLock.acquire();
    }

}

